package cn.datawin.bms.modules.base.service.impl;

import cn.datawin.bms.base.entity.BaseAreaNumberEntity;
import cn.datawin.bms.modules.base.mapper.BaseAreaNumberMapper;
import cn.datawin.bms.modules.base.service.BaseAreaNumberService;
import cn.datawin.common.core.util.RedisUtils;
import cn.datawin.constant.RedisPattern;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 号码段
 *
 * @author datawin-sms
 * @date 2025-09-10 16:56:52
 */
@Service
@Slf4j
public class BaseAreaNumberServiceImpl extends ServiceImpl<BaseAreaNumberMapper, BaseAreaNumberEntity> implements BaseAreaNumberService {
	@Override
	public void refreshCache() {
		DateTime d1 = new DateTime();
		List<String> keysForPage = RedisUtils.findKeysForPage(RedisPattern.BASE_AREA_NUMBER_PREFIX.replaceAll(":%s", "") + "*", 1, 1000000);
		if(CollUtil.isNotEmpty(keysForPage)) {
			for (String s : keysForPage) {
				RedisUtils.del(s);
			}

		}
		log.info("删除原有归属地数据缓存---{}条",keysForPage.size());
		QueryWrapper<BaseAreaNumberEntity> qw = new QueryWrapper<>();
		qw.orderByAsc("id");
		qw.last("limit 1");
		List<BaseAreaNumberEntity> baseAreaNumberList = this.baseMapper.selectList(qw);
		if(CollUtil.isEmpty(baseAreaNumberList)) return;
		AtomicInteger allCount = new AtomicInteger(0);
		BaseAreaNumberEntity baseAreaNumber = baseAreaNumberList.get(0);
		toCache(baseAreaNumber);
		allCount.incrementAndGet();
		log.info("初始化归属地数据到缓存---{}条",1);
		Long lastId = baseAreaNumber.getId();
		int limit =1000;
		int threadNum = 10;
		ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
		List<BaseAreaNumberEntity> batchData = getBatchData(lastId, limit);
		while(CollUtil.isNotEmpty(batchData)){
			List<List<BaseAreaNumberEntity>> partition = Lists.partition(batchData, threadNum);
			int size = partition.size();
			CountDownLatch countDownLatch = new CountDownLatch(size);
			for (List<BaseAreaNumberEntity> baseAreaNumberEntities : partition) {
				executorService.submit(() -> {
					try{
						for (BaseAreaNumberEntity batchDatum : baseAreaNumberEntities) {

							try{
								toCache(batchDatum);
								allCount.incrementAndGet();
							}catch (Exception e){
								log.error("插入异常---"+batchDatum.getNumberPart(),e);
							}

						}
					}catch (Exception e){
						e.printStackTrace();
					}finally {
						countDownLatch.countDown();
					}

				});
			}
			try {
				countDownLatch.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			log.info("初始化归属地数据到缓存---{}条--已处理{}条",batchData.size(),allCount.get());
			lastId = batchData.get(batchData.size()-1).getId();
			batchData = getBatchData(lastId, limit);
		}
		DateTime d2 = new DateTime();
		int seconds = new Period(d1, d2).toStandardSeconds().getSeconds();
		log.info("初始化归属地数据到缓存---耗时{}秒--共{}条" , seconds,allCount);
	}


	public void toCache(BaseAreaNumberEntity baseAreaNumber) {
		int prefix = Integer.parseInt(baseAreaNumber.getPrefix());
		String numberPart = baseAreaNumber.getNumberPart();
		int suffix = Integer.parseInt(numberPart.substring(3));

		JSONObject json = new JSONObject();
		json.put("provinceCode",baseAreaNumber.getProvinceCode());
		json.put("cityCode",baseAreaNumber.getCityCode());
		json.put("ispCode",baseAreaNumber.getIspCode());
		String redisKey = String.format(RedisPattern.BASE_AREA_NUMBER_PREFIX, prefix);
		RedisUtils.hset(redisKey,suffix+"",json.toJSONString());
	}
	private List<BaseAreaNumberEntity> getBatchData(Long lastId, int limit) {
		QueryWrapper<BaseAreaNumberEntity> qw = new QueryWrapper<>();
		qw.gt("id",lastId);
		qw.orderByAsc("id");
		qw.last("limit "+limit);
		List<BaseAreaNumberEntity> baseAreaNumbers = this.baseMapper.selectList(qw);
		if(CollUtil.isEmpty(baseAreaNumbers)) return Collections.emptyList();
		return baseAreaNumbers;
	}
}
